package com.yxw.live_vod_backend_boot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxw.live_vod_backend_boot.dto.menu.MenuAddDTO;
import com.yxw.live_vod_backend_boot.dto.menu.MenuQueryDTO;
import com.yxw.live_vod_backend_boot.dto.menu.MenuUpdateDTO;
import com.yxw.live_vod_backend_boot.entity.YxCsMenuEntity;
import com.yxw.live_vod_backend_boot.entity.YxCsUserEntity;
import com.yxw.live_vod_backend_boot.mapper.MenuMapper;
import com.yxw.live_vod_backend_boot.mapper.RoleMapper;
import com.yxw.live_vod_backend_boot.mapper.UserMapper;
import com.yxw.live_vod_backend_boot.service.MenuService;
import com.yxw.live_vod_backend_boot.util.StringUtil;
import com.yxw.live_vod_backend_boot.util.TreeSelect;
import com.yxw.live_vod_backend_boot.util.UserUtil;
import com.yxw.live_vod_backend_boot.vo.YxCsMenuVo;
import com.yxw.yxnet_cd_center.common.constant.UserConstants;
import com.yxw.yxnet_cd_center.common.enums.CommonErrorEnum;
import com.yxw.yxnet_cd_center.common.exception.BaseException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author fangmaoxin
 * @version 1.0
 * @date 2023年9月17日
 * 菜单管理 服务类
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, YxCsMenuEntity> implements MenuService {

    @Autowired
    private UserUtil userUtil;

    @Autowired
    private MenuMapper sysMenuMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserMapper userMapper;

    private static final String LAST_STR = "LIMIT 1";


    /**
     * 根据用户查询系统菜单列表
     *
     * @param userId 用户ID
     * @return 菜单列表
     */
//    @Override
//    public List<YxCsSysMenuEntity> selectMenuList(Long userId) {
//        return selectMenuList(new YxCsSysMenuEntity(), userId);
//    }

    /**
     * 查询系统菜单列表
     *
     * @return 菜单列表
     */
    @Override
    public List<YxCsMenuVo> selectMenuList(MenuQueryDTO dto) {
        LambdaQueryWrapper<YxCsMenuEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 设置查询条件
        if (StringUtil.isNotBlank(dto.getMenuName())) {
            queryWrapper.like(YxCsMenuEntity::getMenuName, "%" + dto.getMenuName() + "%");
        }
        // 设置过滤条件
//        queryWrapper.eq(YxCsSysMenuEntity::getVisible, 0)
//                .eq(YxCsSysMenuEntity::getStatus, 0);
        // 设置排序方式
        queryWrapper.orderByDesc(YxCsMenuEntity::getCreateTime);
        // 执行查询

        List<YxCsMenuEntity> entityList = baseMapper.selectList(queryWrapper);
        // 使用BeanUtils.copyProperties()将属性复制到YxCsMenuVo列表
        List<YxCsMenuVo> menuVoList = new ArrayList<>();
        if (null != entityList && !entityList.isEmpty()) {
            menuVoList = BeanUtil.copyToList(entityList, YxCsMenuVo.class);
        }
        return menuVoList;
    }

    /**
     * 根据菜单ID查询信息
     *
     * @param menuId 菜单ID
     * @return 菜单信息
     */
    @Override
    public YxCsMenuEntity selectMenuById(Long menuId) {
        LambdaQueryWrapper<YxCsMenuEntity> wrapper = new LambdaQueryWrapper<YxCsMenuEntity>().eq(YxCsMenuEntity::getMenuId, menuId);
        return baseMapper.selectOne(wrapper);
    }


    /**
     * 获取菜单下拉树列表
     */
    @Override
    public List<TreeSelect> buildMenuTreeSelect(List<YxCsMenuVo> menus) {
        List<YxCsMenuVo> menuTrees = buildMenuTree(menus);
        return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 校验菜单名称是否唯一
     *
     * @param dto 菜单信息
     * @return 结果
     */
    @Override
    public boolean checkMenuNameUnique(MenuAddDTO dto) {

        LambdaQueryWrapper<YxCsMenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YxCsMenuEntity::getMenuName, dto.getMenuName())
                .eq(YxCsMenuEntity::getParentId, dto.getParentId())
                .last(LAST_STR);
        YxCsMenuEntity info = baseMapper.selectOne(wrapper);
        if (StringUtil.isNotNull(info)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public boolean checkMenuNameUnique(MenuUpdateDTO dto) {
        long menuId = StringUtil.isNull(dto.getMenuId()) ? -1L : dto.getMenuId();
        LambdaQueryWrapper<YxCsMenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YxCsMenuEntity::getMenuName, dto.getMenuName())
                .eq(YxCsMenuEntity::getParentId, dto.getParentId())
                .last(LAST_STR);
        YxCsMenuEntity info = baseMapper.selectOne(wrapper);
        if (StringUtil.isNotNull(info) && info.getMenuId() != menuId) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验菜单排序序号是否唯一
     *
     * @return 结果
     */
    @Override
    public boolean checkMenuOrderNumUnique(MenuAddDTO dto) {
        Long parentId = dto.getParentId(); // 获取父菜单ID
        Integer orderNum = dto.getOrderNum(); // 获取排序序号

        LambdaQueryWrapper<YxCsMenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YxCsMenuEntity::getParentId, parentId) // 添加父菜单ID的检索条件
                .eq(YxCsMenuEntity::getOrderNum, orderNum) // 添加排序序号的检索条件
                .last(LAST_STR);

        YxCsMenuEntity info = baseMapper.selectOne(wrapper);
        if (StringUtil.isNotNull(info)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public boolean checkMenuOrderNumUnique(MenuUpdateDTO dto) {
        long menuId = StringUtil.isNull(dto.getMenuId()) ? -1L : dto.getMenuId();
        Long parentId = dto.getParentId(); // 获取父菜单ID
        Integer orderNum = dto.getOrderNum(); // 获取排序序号

        LambdaQueryWrapper<YxCsMenuEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YxCsMenuEntity::getParentId, parentId) // 添加父菜单ID的检索条件
                .eq(YxCsMenuEntity::getOrderNum, orderNum) // 添加排序序号的检索条件
                .last(LAST_STR);

        YxCsMenuEntity info = baseMapper.selectOne(wrapper);
        if (StringUtil.isNotNull(info) && info.getMenuId() != menuId) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增保存菜单信息
     *
     * @param menu 菜单信息
     * @return 结果
     */
    @Override
    @Transactional
    public int insertMenu(YxCsMenuEntity menu) {
        menu.setCreateTime(new Date());
        if (userUtil.getLoginName() != null) {
            menu.setCreateBy(userUtil.getLoginName());
        }
        return baseMapper.insert(menu);
    }


    /**
     * 修改保存菜单信息
     *
     * @param menu 菜单信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateMenu(YxCsMenuEntity menu) {
        Long menuId = menu.getMenuId();
        if (baseMapper.selectById(menuId) == null) {
            throw new BaseException(CommonErrorEnum.DATA_NOT_EXISTED_EXCEPTION);
        }
        menu.setUpdateTime(new Date());
        if (userUtil.getLoginName() != null) {
            menu.setUpdateBy(userUtil.getLoginName());
        }
        return baseMapper.updateById(menu);
    }

    /**
     * 删除菜单管理信息
     *
     * @param menuId 菜单ID
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteMenuById(Long menuId) {
        if (baseMapper.selectById(menuId) == null) {
            throw new BaseException(CommonErrorEnum.DATA_DELETED_EXCEPTION);
        }
        return baseMapper.deleteById(menuId);
    }

    /**
     * 菜单树列表
     */
    @Override
    public List<YxCsMenuVo> menuTree(MenuQueryDTO dto) {
        List<YxCsMenuVo> result = new ArrayList<>();
        LambdaQueryWrapper<YxCsMenuEntity> wrapper = new LambdaQueryWrapper<>();
        // 设置查询条件
        if (StringUtils.isNotBlank(dto.getMenuName())) {
            wrapper.like(YxCsMenuEntity::getMenuName, "%" + dto.getMenuName() + "%");
        }
        // 设置排序方式
        wrapper.orderByDesc(YxCsMenuEntity::getCreateTime);
        List<YxCsMenuEntity> menuList = baseMapper.selectList(wrapper);
        List<YxCsMenuVo> menuVos = BeanUtil.copyToList(menuList, YxCsMenuVo.class);
        Map<Long, YxCsMenuVo> menuMap = menuVos.stream().collect(Collectors.toMap(YxCsMenuVo::getMenuId, menu -> menu));
        menuVos.forEach(menu -> {
            if (menu.getParentId() == 0) {
                result.add(menu);
            } else {
                YxCsMenuVo parent = menuMap.get(menu.getParentId());
                if (parent != null) {
                    parent.getChildren().add(menu);
                }
            }
        });
        return result;
    }

    /**
     * 加载对应用户菜单列表树
     */
    @Override
    public List<YxCsMenuVo> getMenuTreeByUserRole(Long userId, MenuQueryDTO dto) {
        if (userId == null) {
            throw new BaseException("2001", null, "获取UserId失败，请重新登录尝试。");
        } else {
            YxCsUserEntity userEntity = userMapper.selectById(userId);
            if (userEntity != null && "admin".equals(userEntity.getUserNum())) {
                List<YxCsMenuEntity> menuEntities = baseMapper.selectList(new LambdaQueryWrapper<>());
                // 构建菜单树
                List<YxCsMenuVo> menuVos = BeanUtil.copyToList(menuEntities, YxCsMenuVo.class);
                return buildMenuTree(menuVos, 0L);
            } else {
                // 查询员工与菜单关联表，获取菜单id列表
                List<Long> userMenuIds = roleMapper.selectMenuIdsByUserId(userId);
                if (userMenuIds.isEmpty()) {
                    throw new BaseException("2002", null, "该用户没有可访问的菜单。");
                }
                // 设置查询条件
                LambdaQueryWrapper<YxCsMenuEntity> menuWrapper = new LambdaQueryWrapper<>();
                if (StringUtils.isNotBlank(dto.getMenuName())) {
                    menuWrapper.like(YxCsMenuEntity::getMenuName, "%" + dto.getMenuName() + "%");
                }
                menuWrapper.in(YxCsMenuEntity::getMenuId, userMenuIds);
                List<YxCsMenuEntity> menuList = baseMapper.selectList(menuWrapper);
                List<YxCsMenuVo> menuVos = BeanUtil.copyToList(menuList, YxCsMenuVo.class);
                // 构建菜单树
                return buildMenuTree(menuVos, 0L);

            }
        }
    }

    private List<YxCsMenuVo> buildMenuTree(List<YxCsMenuVo> menuVos, Long parentId) {
        List<YxCsMenuVo> tree = new ArrayList<>();
        for (YxCsMenuVo menuVo : menuVos) {
            if (parentId.equals(menuVo.getParentId())) {
                List<YxCsMenuVo> children = buildMenuTree(menuVos, menuVo.getMenuId());
                menuVo.setChildren(children);
                tree.add(menuVo);
            }
        }
        return tree;
    }

    /**
     * 查询菜单是否存在角色
     *
     * @param menuId 菜单ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkMenuExistRole(Long menuId) {
        int result = sysMenuMapper.checkMenuExistRole(menuId);
        return result > 0;
    }


    /**
     * 是否存在菜单子节点
     *
     * @param menuId 菜单ID
     * @return 结果
     */
    @Override
    public boolean hasChildByMenuId(Long menuId) {
        LambdaQueryWrapper<YxCsMenuEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(YxCsMenuEntity::getParentId, menuId);

        int count = baseMapper.selectCount(queryWrapper);
        return count > 0;
    }


    /**
     * 查询菜单使用数量
     *
     * @param menuId 菜单ID
     * @return 结果
     */
    // todo
//    @Override
//    public boolean checkMenuExistRole(Long menuId)
//    {
//        int result = roleMenuMapper.checkMenuExistRole(menuId);
//        return result > 0;
//    }

    /**
     * 根据角色ID查询菜单树信息
     *
     * @param roleId 角色ID
     * @return 选中菜单列表
     */
//    @Override
//    public List<Long> selectMenuListByRoleId(Long roleId)
//    {
//        SysRole role = roleMapper.selectRoleById(roleId);
//        return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
//    }

    /**
     * 构建前端所需要树结构
     *
     * @param menus 菜单列表
     * @return 树结构列表
     */
    @Override
    public List<YxCsMenuVo> buildMenuTree(List<YxCsMenuVo> menus) {
        List<YxCsMenuVo> returnList = new ArrayList<>();
        List<Long> tempList = menus.stream().map(YxCsMenuEntity::getMenuId).collect(Collectors.toList());
        for (YxCsMenuVo menu : menus) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(menu.getParentId())) {
                recursionFn(menus, menu);
                returnList.add(menu);
            }
        }
        if (returnList.isEmpty()) {
            returnList = menus;
        }
        return returnList;
    }

    /**
     * 递归列表
     *
     * @param list 分类表
     * @param t    子节点
     */
    private void recursionFn(List<YxCsMenuVo> list, YxCsMenuVo t) {
        // 得到子节点列表
        List<YxCsMenuVo> childList = getChildList(list, t);
        t.setChildren(childList);
        for (YxCsMenuVo tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<YxCsMenuVo> getChildList(List<YxCsMenuVo> list, YxCsMenuVo t) {
        List<YxCsMenuVo> tlist = new ArrayList<>();
        for (YxCsMenuVo n : list) {
            if (n.getParentId().longValue() == t.getMenuId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<YxCsMenuVo> list, YxCsMenuVo t) {
        return !getChildList(list, t).isEmpty();
    }
}